{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ef0a4ee4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C:\\\\Users\\\\oscar'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%pwd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "japanese-margin",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C:\\\\Users\\\\oscar'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "os.getcwd()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "executive-insulin",
   "metadata": {},
   "outputs": [],
   "source": [
    "os.chdir('C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\FOUR_CARNIVORES')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "0888b480",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\FOUR_CARNIVORES'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%pwd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d29220ca",
   "metadata": {},
   "outputs": [],
   "source": [
    "from tensorflow import keras\n",
    "#keras.__version__\n",
    "import os, shutil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "d979c4e9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C:\\Users\\oscar\\Documents\\MOMOCS\\FOUR_CARNIVORES\n",
      "C:\\Users\\oscar\\Documents\\MOMOCS\\FOUR_CARNIVORES\\conv\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "#create a folder named \"conv2\" in directory\n",
    "original_dir = os.path.abspath('C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\FOUR_CARNIVORES')\n",
    "# The directory where we will\n",
    "# store our smaller dataset\n",
    "base_dir = os.path.join(original_dir, \"conv\")\n",
    "print(original_dir)\n",
    "print(base_dir)\n",
    "# added by reviewer\n",
    "isdir = os.path.isdir(base_dir) \n",
    "print(isdir) \n",
    "\n",
    "if isdir ==True:\n",
    "    shutil.rmtree(base_dir)\n",
    "\n",
    "os.mkdir(base_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "6b486b83",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Directories for our training,\n",
    "# validation and test splits\n",
    "train_dir = os.path.join(base_dir, 'train')\n",
    "os.mkdir(train_dir)\n",
    "validation_dir = os.path.join(base_dir, 'validation')\n",
    "os.mkdir(validation_dir)\n",
    "\n",
    "# Directory with our training crocodile pictures\n",
    "train_croc_dir = os.path.join(train_dir, 'CFP')\n",
    "os.mkdir(train_croc_dir)\n",
    "\n",
    "# Directory with our training hyena pictures\n",
    "train_hyena_dir = os.path.join(train_dir, 'HESP')\n",
    "os.mkdir(train_hyena_dir)\n",
    "\n",
    "# Directory with our training leopard pictures\n",
    "train_leop_dir = os.path.join(train_dir, 'LPZP')\n",
    "os.mkdir(train_leop_dir)\n",
    "\n",
    "# Directory with our training lion pictures\n",
    "train_lion_dir = os.path.join(train_dir, 'LZP')\n",
    "os.mkdir(train_lion_dir)\n",
    "\n",
    "\n",
    "# Directory with our validation hyena pictures\n",
    "validation_croc_dir = os.path.join(validation_dir, 'CFP')\n",
    "os.mkdir(validation_croc_dir)\n",
    "\n",
    "# Directory with our validation hyena pictures\n",
    "validation_hyena_dir = os.path.join(validation_dir, 'HESP')\n",
    "os.mkdir(validation_hyena_dir)\n",
    "\n",
    "# Directory with our validation leopard pictures\n",
    "validation_leop_dir = os.path.join(validation_dir, 'LPZP')\n",
    "os.mkdir(validation_leop_dir)\n",
    "\n",
    "# Directory with our validation lion pictures\n",
    "validation_lion_dir = os.path.join(validation_dir, 'LZP')\n",
    "os.mkdir(validation_lion_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "convenient-least",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "61\n",
      "['CFP.56.bmp', 'CFP.47.bmp', 'CFP.40.bmp', 'CFP.3.bmp', 'CFP.38.bmp', 'CFP.14.bmp', 'CFP.72.bmp', 'CFP.22.bmp', 'CFP.57.bmp', 'CFP.32.bmp', 'CFP.80.bmp', 'CFP.44.bmp', 'CFP.25.bmp', 'CFP.51.bmp', 'CFP.6.bmp', 'CFP.70.bmp', 'CFP.74.bmp', 'CFP.65.bmp', 'CFP.71.bmp', 'CFP.36.bmp', 'CFP.21.bmp', 'CFP.81.bmp', 'CFP.69.bmp', 'CFP.13.bmp', 'CFP.7.bmp', 'CFP.68.bmp', 'CFP.79.bmp', 'CFP.33.bmp', 'CFP.10.bmp', 'CFP.82.bmp', 'CFP.77.bmp', 'CFP.75.bmp', 'CFP.30.bmp', 'CFP.27.bmp', 'CFP.64.bmp', 'CFP.76.bmp', 'CFP.84.bmp', 'CFP.63.bmp', 'CFP.34.bmp', 'CFP.55.bmp', 'CFP.12.bmp', 'CFP.83.bmp', 'CFP.50.bmp', 'CFP.0.bmp', 'CFP.37.bmp', 'CFP.2.bmp', 'CFP.24.bmp', 'CFP.39.bmp', 'CFP.28.bmp', 'CFP.15.bmp', 'CFP.49.bmp', 'CFP.58.bmp', 'CFP.8.bmp', 'CFP.23.bmp', 'CFP.42.bmp', 'CFP.19.bmp', 'CFP.60.bmp', 'CFP.11.bmp', 'CFP.29.bmp', 'CFP.16.bmp', 'CFP.43.bmp']\n",
      "26\n",
      "['CFP.52.bmp', 'CFP.18.bmp', 'CFP.67.bmp', 'CFP.48.bmp', 'CFP.45.bmp', 'CFP.17.bmp', 'CFP.53.bmp', 'CFP.5.bmp', 'CFP.46.bmp', 'CFP.31.bmp', 'CFP.9.bmp', 'CFP.41.bmp', 'CFP.78.bmp', 'CFP.66.bmp', 'CFP.85.bmp', 'CFP.20.bmp', 'CFP.35.bmp', 'CFP.62.bmp', 'CFP.59.bmp', 'CFP.26.bmp', 'CFP.1.bmp', 'CFP.86.bmp', 'CFP.61.bmp', 'CFP.54.bmp', 'CFP.4.bmp', 'CFP.73.bmp']\n",
      "144\n",
      "['HESP.37.bmp', 'HESP.14.bmp', 'HESP.196.bmp', 'HESP.165.bmp', 'HESP.23.bmp', 'HESP.89.bmp', 'HESP.76.bmp', 'HESP.130.bmp', 'HESP.70.bmp', 'HESP.199.bmp', 'HESP.54.bmp', 'HESP.183.bmp', 'HESP.45.bmp', 'HESP.39.bmp', 'HESP.104.bmp', 'HESP.179.bmp', 'HESP.81.bmp', 'HESP.7.bmp', 'HESP.13.bmp', 'HESP.152.bmp', 'HESP.162.bmp', 'HESP.151.bmp', 'HESP.178.bmp', 'HESP.78.bmp', 'HESP.25.bmp', 'HESP.198.bmp', 'HESP.46.bmp', 'HESP.155.bmp', 'HESP.36.bmp', 'HESP.163.bmp', 'HESP.189.bmp', 'HESP.108.bmp', 'HESP.129.bmp', 'HESP.50.bmp', 'HESP.119.bmp', 'HESP.88.bmp', 'HESP.94.bmp', 'HESP.43.bmp', 'HESP.68.bmp', 'HESP.150.bmp', 'HESP.65.bmp', 'HESP.64.bmp', 'HESP.32.bmp', 'HESP.27.bmp', 'HESP.47.bmp', 'HESP.75.bmp', 'HESP.182.bmp', 'HESP.29.bmp', 'HESP.114.bmp', 'HESP.6.bmp', 'HESP.142.bmp', 'HESP.195.bmp', 'HESP.103.bmp', 'HESP.200.bmp', 'HESP.4.bmp', 'HESP.117.bmp', 'HESP.181.bmp', 'HESP.166.bmp', 'HESP.101.bmp', 'HESP.2.bmp', 'HESP.192.bmp', 'HESP.26.bmp', 'HESP.139.bmp', 'HESP.12.bmp', 'HESP.56.bmp', 'HESP.85.bmp', 'HESP.73.bmp', 'HESP.180.bmp', 'HESP.100.bmp', 'HESP.202.bmp', 'HESP.17.bmp', 'HESP.86.bmp', 'HESP.59.bmp', 'HESP.62.bmp', 'HESP.203.bmp', 'HESP.141.bmp', 'HESP.82.bmp', 'HESP.102.bmp', 'HESP.170.bmp', 'HESP.168.bmp', 'HESP.177.bmp', 'HESP.30.bmp', 'HESP.188.bmp', 'HESP.160.bmp', 'HESP.158.bmp', 'HESP.74.bmp', 'HESP.51.bmp', 'HESP.122.bmp', 'HESP.33.bmp', 'HESP.10.bmp', 'HESP.126.bmp', 'HESP.205.bmp', 'HESP.201.bmp', 'HESP.5.bmp', 'HESP.91.bmp', 'HESP.69.bmp', 'HESP.0.bmp', 'HESP.131.bmp', 'HESP.124.bmp', 'HESP.194.bmp', 'HESP.191.bmp', 'HESP.134.bmp', 'HESP.143.bmp', 'HESP.106.bmp', 'HESP.99.bmp', 'HESP.153.bmp', 'HESP.144.bmp', 'HESP.148.bmp', 'HESP.84.bmp', 'HESP.21.bmp', 'HESP.132.bmp', 'HESP.58.bmp', 'HESP.161.bmp', 'HESP.15.bmp', 'HESP.110.bmp', 'HESP.22.bmp', 'HESP.66.bmp', 'HESP.79.bmp', 'HESP.138.bmp', 'HESP.184.bmp', 'HESP.87.bmp', 'HESP.31.bmp', 'HESP.145.bmp', 'HESP.53.bmp', 'HESP.55.bmp', 'HESP.175.bmp', 'HESP.121.bmp', 'HESP.48.bmp', 'HESP.42.bmp', 'HESP.113.bmp', 'HESP.24.bmp', 'HESP.28.bmp', 'HESP.135.bmp', 'HESP.95.bmp', 'HESP.98.bmp', 'HESP.38.bmp', 'HESP.20.bmp', 'HESP.136.bmp', 'HESP.18.bmp', 'HESP.159.bmp', 'HESP.127.bmp', 'HESP.193.bmp', 'HESP.9.bmp', 'HESP.156.bmp']\n",
      "62\n",
      "['HESP.105.bmp', 'HESP.57.bmp', 'HESP.40.bmp', 'HESP.128.bmp', 'HESP.190.bmp', 'HESP.164.bmp', 'HESP.16.bmp', 'HESP.120.bmp', 'HESP.111.bmp', 'HESP.115.bmp', 'HESP.140.bmp', 'HESP.80.bmp', 'HESP.173.bmp', 'HESP.93.bmp', 'HESP.137.bmp', 'HESP.174.bmp', 'HESP.49.bmp', 'HESP.171.bmp', 'HESP.60.bmp', 'HESP.1.bmp', 'HESP.149.bmp', 'HESP.186.bmp', 'HESP.96.bmp', 'HESP.157.bmp', 'HESP.112.bmp', 'HESP.61.bmp', 'HESP.176.bmp', 'HESP.34.bmp', 'HESP.187.bmp', 'HESP.169.bmp', 'HESP.77.bmp', 'HESP.44.bmp', 'HESP.116.bmp', 'HESP.67.bmp', 'HESP.172.bmp', 'HESP.72.bmp', 'HESP.185.bmp', 'HESP.97.bmp', 'HESP.90.bmp', 'HESP.154.bmp', 'HESP.35.bmp', 'HESP.107.bmp', 'HESP.11.bmp', 'HESP.92.bmp', 'HESP.63.bmp', 'HESP.19.bmp', 'HESP.83.bmp', 'HESP.197.bmp', 'HESP.133.bmp', 'HESP.204.bmp', 'HESP.41.bmp', 'HESP.167.bmp', 'HESP.71.bmp', 'HESP.125.bmp', 'HESP.118.bmp', 'HESP.52.bmp', 'HESP.3.bmp', 'HESP.147.bmp', 'HESP.123.bmp', 'HESP.109.bmp', 'HESP.8.bmp', 'HESP.146.bmp']\n",
      "85\n",
      "['LPZP.39.bmp', 'LPZP.72.bmp', 'LPZP.115.bmp', 'LPZP.29.bmp', 'LPZP.18.bmp', 'LPZP.88.bmp', 'LPZP.117.bmp', 'LPZP.75.bmp', 'LPZP.113.bmp', 'LPZP.109.bmp', 'LPZP.11.bmp', 'LPZP.52.bmp', 'LPZP.27.bmp', 'LPZP.50.bmp', 'LPZP.65.bmp', 'LPZP.49.bmp', 'LPZP.64.bmp', 'LPZP.63.bmp', 'LPZP.44.bmp', 'LPZP.25.bmp', 'LPZP.3.bmp', 'LPZP.43.bmp', 'LPZP.16.bmp', 'LPZP.94.bmp', 'LPZP.93.bmp', 'LPZP.8.bmp', 'LPZP.21.bmp', 'LPZP.112.bmp', 'LPZP.81.bmp', 'LPZP.67.bmp', 'LPZP.13.bmp', 'LPZP.89.bmp', 'LPZP.12.bmp', 'LPZP.79.bmp', 'LPZP.28.bmp', 'LPZP.6.bmp', 'LPZP.7.bmp', 'LPZP.69.bmp', 'LPZP.47.bmp', 'LPZP.23.bmp', 'LPZP.90.bmp', 'LPZP.71.bmp', 'LPZP.101.bmp', 'LPZP.76.bmp', 'LPZP.34.bmp', 'LPZP.107.bmp', 'LPZP.42.bmp', 'LPZP.70.bmp', 'LPZP.19.bmp', 'LPZP.100.bmp', 'LPZP.51.bmp', 'LPZP.2.bmp', 'LPZP.15.bmp', 'LPZP.114.bmp', 'LPZP.14.bmp', 'LPZP.91.bmp', 'LPZP.10.bmp', 'LPZP.32.bmp', 'LPZP.118.bmp', 'LPZP.106.bmp', 'LPZP.37.bmp', 'LPZP.102.bmp', 'LPZP.110.bmp', 'LPZP.60.bmp', 'LPZP.55.bmp', 'LPZP.57.bmp', 'LPZP.40.bmp', 'LPZP.116.bmp', 'LPZP.108.bmp', 'LPZP.68.bmp', 'LPZP.85.bmp', 'LPZP.24.bmp', 'LPZP.82.bmp', 'LPZP.80.bmp', 'LPZP.0.bmp', 'LPZP.74.bmp', 'LPZP.97.bmp', 'LPZP.92.bmp', 'LPZP.78.bmp', 'LPZP.56.bmp', 'LPZP.30.bmp', 'LPZP.87.bmp', 'LPZP.99.bmp', 'LPZP.98.bmp', 'LPZP.84.bmp']\n",
      "36\n",
      "['LPZP.38.bmp', 'LPZP.22.bmp', 'LPZP.58.bmp', 'LPZP.33.bmp', 'LPZP.86.bmp', 'LPZP.36.bmp', 'LPZP.96.bmp', 'LPZP.48.bmp', 'LPZP.45.bmp', 'LPZP.77.bmp', 'LPZP.17.bmp', 'LPZP.53.bmp', 'LPZP.5.bmp', 'LPZP.46.bmp', 'LPZP.95.bmp', 'LPZP.31.bmp', 'LPZP.9.bmp', 'LPZP.41.bmp', 'LPZP.111.bmp', 'LPZP.66.bmp', 'LPZP.119.bmp', 'LPZP.20.bmp', 'LPZP.103.bmp', 'LPZP.83.bmp', 'LPZP.35.bmp', 'LPZP.105.bmp', 'LPZP.62.bmp', 'LPZP.104.bmp', 'LPZP.59.bmp', 'LPZP.26.bmp', 'LPZP.1.bmp', 'LPZP.120.bmp', 'LPZP.61.bmp', 'LPZP.54.bmp', 'LPZP.4.bmp', 'LPZP.73.bmp']\n",
      "92\n",
      "['LZP.18.bmp', 'LZP.51.bmp', 'LZP.106.bmp', 'LZP.37.bmp', 'LZP.43.bmp', 'LZP.72.bmp', 'LZP.44.bmp', 'LZP.2.bmp', 'LZP.47.bmp', 'LZP.112.bmp', 'LZP.92.bmp', 'LZP.16.bmp', 'LZP.127.bmp', 'LZP.25.bmp', 'LZP.14.bmp', 'LZP.32.bmp', 'LZP.1.bmp', 'LZP.61.bmp', 'LZP.85.bmp', 'LZP.75.bmp', 'LZP.13.bmp', 'LZP.122.bmp', 'LZP.121.bmp', 'LZP.39.bmp', 'LZP.125.bmp', 'LZP.119.bmp', 'LZP.116.bmp', 'LZP.71.bmp', 'LZP.69.bmp', 'LZP.21.bmp', 'LZP.101.bmp', 'LZP.115.bmp', 'LZP.29.bmp', 'LZP.50.bmp', 'LZP.88.bmp', 'LZP.11.bmp', 'LZP.100.bmp', 'LZP.49.bmp', 'LZP.120.bmp', 'LZP.15.bmp', 'LZP.79.bmp', 'LZP.126.bmp', 'LZP.27.bmp', 'LZP.98.bmp', 'LZP.12.bmp', 'LZP.10.bmp', 'LZP.80.bmp', 'LZP.6.bmp', 'LZP.7.bmp', 'LZP.90.bmp', 'LZP.73.bmp', 'LZP.23.bmp', 'LZP.102.bmp', 'LZP.82.bmp', 'LZP.113.bmp', 'LZP.97.bmp', 'LZP.54.bmp', 'LZP.34.bmp', 'LZP.76.bmp', 'LZP.42.bmp', 'LZP.81.bmp', 'LZP.67.bmp', 'LZP.19.bmp', 'LZP.63.bmp', 'LZP.65.bmp', 'LZP.117.bmp', 'LZP.89.bmp', 'LZP.52.bmp', 'LZP.28.bmp', 'LZP.118.bmp', 'LZP.64.bmp', 'LZP.114.bmp', 'LZP.130.bmp', 'LZP.60.bmp', 'LZP.55.bmp', 'LZP.57.bmp', 'LZP.70.bmp', 'LZP.40.bmp', 'LZP.111.bmp', 'LZP.94.bmp', 'LZP.68.bmp', 'LZP.96.bmp', 'LZP.24.bmp', 'LZP.93.bmp', 'LZP.91.bmp', 'LZP.0.bmp', 'LZP.74.bmp', 'LZP.129.bmp', 'LZP.124.bmp', 'LZP.78.bmp', 'LZP.56.bmp', 'LZP.30.bmp']\n",
      "39\n",
      "['LZP.99.bmp', 'LZP.107.bmp', 'LZP.110.bmp', 'LZP.84.bmp', 'LZP.38.bmp', 'LZP.87.bmp', 'LZP.22.bmp', 'LZP.58.bmp', 'LZP.33.bmp', 'LZP.86.bmp', 'LZP.36.bmp', 'LZP.108.bmp', 'LZP.48.bmp', 'LZP.45.bmp', 'LZP.77.bmp', 'LZP.17.bmp', 'LZP.53.bmp', 'LZP.5.bmp', 'LZP.46.bmp', 'LZP.95.bmp', 'LZP.31.bmp', 'LZP.9.bmp', 'LZP.41.bmp', 'LZP.128.bmp', 'LZP.66.bmp', 'LZP.4.bmp', 'LZP.20.bmp', 'LZP.103.bmp', 'LZP.83.bmp', 'LZP.35.bmp', 'LZP.105.bmp', 'LZP.62.bmp', 'LZP.104.bmp', 'LZP.59.bmp', 'LZP.26.bmp', 'LZP.3.bmp', 'LZP.123.bmp', 'LZP.109.bmp', 'LZP.8.bmp']\n"
     ]
    }
   ],
   "source": [
    "#USE THIS ONE\n",
    "\n",
    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
    "# randomize order of image locations\n",
    "# this will help model in not being data sequence dependent\n",
    "\n",
    "# Copy first CM images to train_lion_dir\n",
    "import random\n",
    "    \n",
    "    \n",
    "# Copy first TM images to train_croc_dir # \n",
    "fnames = ['CFP.{}.bmp'.format(i) for i in range(87)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:61]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_croc_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "        \n",
    "# Copy next TM images to validation_croc_dir\n",
    "fnamesv = fnames[61:87]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_croc_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "    \n",
    "    \n",
    "    \n",
    "# Copy first TM images to train_hyena_dir # \n",
    "fnames = ['HESP.{}.bmp'.format(i) for i in range(206)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:144]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_hyena_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "        \n",
    "# Copy next 10 TM images to validation_hip_dir\n",
    "fnamesv = fnames[144:206]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_hyena_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "    \n",
    "    \n",
    "    \n",
    "# Copy first TM images to train_leop_dir # \n",
    "fnames = ['LPZP.{}.bmp'.format(i) for i in range(121)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:85]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_leop_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "        \n",
    "# Copy next 10 TM images to validation_leop_dir\n",
    "fnamesv = fnames[85:121]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_leop_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "         \n",
    "        \n",
    "\n",
    "\n",
    "# Copy first TM images to train_lion_dir # \n",
    "fnames = ['LZP.{}.bmp'.format(i) for i in range(131)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:92]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_lion_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "        \n",
    "# Copy next 10 TM images to validation_red_dir\n",
    "fnamesv = fnames[92:131]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_lion_dir, fname)\n",
    "    shutil.copyfile(src, dst)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "efe09e3f",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#training and testing sets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "02b116cf",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4e98e48e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "0b730d9a",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 382 images belonging to 4 classes.\n",
      "Found 163 images belonging to 4 classes.\n"
     ]
    }
   ],
   "source": [
    "from tensorflow.keras.applications.densenet import preprocess_input #for RESNET 50\n",
    "#from keras.applications.imagenet_utils import decode_predictions, preprocess_input#for efficient Net\n",
    "#from tensorflow.keras.applications.imagenet_utils import decode_predictions, preprocess_input#for efficient Net\n",
    "\n",
    "#Let's train our network using data augmentation and dropout:\n",
    "train_datagen = ImageDataGenerator(\n",
    "    rotation_range=40,\n",
    "    width_shift_range=0.2,\n",
    "    height_shift_range=0.2,\n",
    "    shear_range=0.2,\n",
    "    zoom_range=0.2,\n",
    "    horizontal_flip=True,\n",
    "    preprocessing_function= \\\n",
    "    keras.applications.densenet.preprocess_input)#OJO!!!! imagenet_utils for Efficient Net\n",
    "\n",
    "# Note that the validation data should not be augmented!\n",
    "test_datagen = ImageDataGenerator(preprocessing_function= \\\n",
    "    keras.applications.densenet.preprocess_input)#OJO!!!\n",
    "\n",
    "train_generator = train_datagen.flow_from_directory(\n",
    "        # This is the target directory\n",
    "        train_dir,\n",
    "        # All images will be resized \n",
    "        target_size=(250, 200),\n",
    "        batch_size=32,\n",
    "        class_mode='categorical')#put \"categorical\" si son más de 2 categorías\n",
    "\n",
    "validation_generator = test_datagen.flow_from_directory(\n",
    "        validation_dir,\n",
    "        target_size=(250, 200),\n",
    "        batch_size=20,\n",
    "        class_mode='categorical',\n",
    "        shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "original-above",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 382 images belonging to 4 classes.\n",
      "Found 163 images belonging to 4 classes.\n",
      "(382, 250, 200, 3) train samples\n",
      "(163, 250, 200, 3) test samples\n"
     ]
    }
   ],
   "source": [
    "datagenTrain=train_datagen.flow_from_directory(\n",
    "        # This is the target directory\n",
    "        train_dir,\n",
    "        # All images will be resized to 40x160\n",
    "        target_size=(250,200),\n",
    "        batch_size=382,\n",
    "        # Since we use binary_crossentropy loss, we need binary labels\n",
    "        class_mode='categorical')\n",
    "datagenTest=test_datagen.flow_from_directory(\n",
    "        # This is the target directory\n",
    "        validation_dir,\n",
    "        # All images will be resized to 40x160\n",
    "        target_size=(250, 200),\n",
    "        batch_size=163,\n",
    "        # Since we use binary_crossentropy loss, we need binary labels\n",
    "        class_mode='categorical',\n",
    "        shuffle=False)\n",
    "x_train, y_train = next(datagenTrain)\n",
    "x_test, y_test = next(datagenTest)\n",
    "print(x_train.shape, 'train samples')\n",
    "print(x_test.shape, 'test samples')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "62521d75",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "af7b5cdc",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#MODULE 2: CHOOSE MODEL"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "0d1d0fac",
   "metadata": {},
   "outputs": [],
   "source": [
    "# For adding new activation function\n",
    "from keras.layers import Activation\n",
    "from keras import backend as K\n",
    "from tensorflow.python.keras.utils.generic_utils import get_custom_objects\n",
    "#from keras.utils.generic_utils import get_custom_objects\n",
    "def swish(x):\n",
    "    return (K.sigmoid(x) * x)\n",
    "\n",
    "get_custom_objects().update({'swish': Activation(swish)})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "566a8bbd",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#activate Dropout "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "ece170ec",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:`lr` is deprecated in Keras optimizer, please use `learning_rate` or use the legacy optimizer, e.g.,tf.keras.optimizers.legacy.Adagrad.\n"
     ]
    }
   ],
   "source": [
    "# Vgg19 for transfer learning with Dropout\n",
    "import sys\n",
    "\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.vgg19 import VGG19\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "#from keras.optimizers import SGD\n",
    "from keras.optimizers import Adagrad\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = VGG19(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\t#opt = SGD(lr=0.001, momentum=0.9)\n",
    "\topt = Adagrad (lr=0.001)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21114903",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "complicated-college",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:`lr` is deprecated in Keras optimizer, please use `learning_rate` or use the legacy optimizer, e.g.,tf.keras.optimizers.legacy.Adagrad.\n"
     ]
    }
   ],
   "source": [
    "# for transfer learning RESNET50 with Dropout\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.resnet50 import ResNet50\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "from keras.optimizers import SGD\n",
    "from keras.optimizers import Adagrad\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = ResNet50(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='swish', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\t#opt = SGD(lr=0.001, momentum=0.9)\n",
    "\topt = Adagrad(lr=0.001)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "50a09b9a",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "be5f7ef8",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:`lr` is deprecated in Keras optimizer, please use `learning_rate` or use the legacy optimizer, e.g.,tf.keras.optimizers.legacy.SGD.\n"
     ]
    }
   ],
   "source": [
    "# for transfer learning DENSENET with Dropout\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.densenet import DenseNet201\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "from keras.optimizers import SGD\n",
    "from keras.optimizers import Adagrad\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = DenseNet201(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile \n",
    "\topt = SGD(lr=0.001, momentum=0.9)   \n",
    "\t#opt = Adagrad(lr=0.001)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "6fc143a8",
   "metadata": {},
   "outputs": [],
   "source": [
    "#RUN MODEL:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "id": "f73ae474",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\oscar\\AppData\\Local\\Temp\\ipykernel_28248\\1142911488.py:2: UserWarning: `Model.fit_generator` is deprecated and will be removed in a future version. Please use `Model.fit`, which supports generators.\n",
      "  history = model.fit_generator(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/100\n",
      "12/12 [==============================] - 41s 3s/step - loss: 32.5460 - accuracy: 0.3586 - val_loss: 1.3501 - val_accuracy: 0.5092\n",
      "Epoch 2/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3758 - accuracy: 0.3874 - val_loss: 1.2624 - val_accuracy: 0.5153\n",
      "Epoch 3/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3276 - accuracy: 0.4031 - val_loss: 1.3466 - val_accuracy: 0.5031\n",
      "Epoch 4/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3711 - accuracy: 0.4503 - val_loss: 1.3344 - val_accuracy: 0.3865\n",
      "Epoch 5/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3044 - accuracy: 0.4136 - val_loss: 1.3152 - val_accuracy: 0.4049\n",
      "Epoch 6/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3527 - accuracy: 0.3927 - val_loss: 1.3367 - val_accuracy: 0.3804\n",
      "Epoch 7/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3402 - accuracy: 0.3770 - val_loss: 1.3373 - val_accuracy: 0.3804\n",
      "Epoch 8/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3396 - accuracy: 0.3770 - val_loss: 1.3367 - val_accuracy: 0.3804\n",
      "Epoch 9/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3391 - accuracy: 0.3770 - val_loss: 1.3364 - val_accuracy: 0.3804\n",
      "Epoch 10/100\n",
      "12/12 [==============================] - 34s 3s/step - loss: 1.3384 - accuracy: 0.3770 - val_loss: 1.3364 - val_accuracy: 0.3804\n",
      "Epoch 11/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3385 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 12/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3388 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 13/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3383 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 14/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3386 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 15/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3385 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 16/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3385 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 17/100\n",
      "12/12 [==============================] - 34s 3s/step - loss: 1.3386 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 18/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3383 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 19/100\n",
      "12/12 [==============================] - 34s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 20/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3384 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 21/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3384 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 22/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3384 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 23/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3387 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 24/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 25/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3361 - val_accuracy: 0.3804\n",
      "Epoch 26/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3359 - accuracy: 0.3822 - val_loss: 1.3126 - val_accuracy: 0.4049\n",
      "Epoch 27/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3369 - accuracy: 0.3901 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 28/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 29/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3384 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 30/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 31/100\n",
      "12/12 [==============================] - 34s 3s/step - loss: 1.3384 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 32/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3385 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 33/100\n",
      "12/12 [==============================] - 34s 3s/step - loss: 1.3384 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 34/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3384 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 35/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3387 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 36/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3384 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 37/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 38/100\n",
      "12/12 [==============================] - 34s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 39/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 40/100\n",
      "12/12 [==============================] - 34s 3s/step - loss: 1.3381 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 41/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3387 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 42/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 43/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3383 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 44/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 45/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3383 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 46/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 47/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3383 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 48/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3384 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 49/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 50/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3383 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 51/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 52/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3383 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 53/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3381 - accuracy: 0.3770 - val_loss: 1.3362 - val_accuracy: 0.3804\n",
      "Epoch 54/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3383 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 55/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3382 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 56/100\n",
      "12/12 [==============================] - 33s 3s/step - loss: 1.3381 - accuracy: 0.3770 - val_loss: 1.3363 - val_accuracy: 0.3804\n",
      "Epoch 57/100\n",
      "12/12 [==============================] - ETA: 0s - loss: 1.3384 - accuracy: 0.3770"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[104], line 2\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# define model\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m history \u001b[38;5;241m=\u001b[39m model\u001b[38;5;241m.\u001b[39mfit_generator(\n\u001b[0;32m      3\u001b[0m       train_generator,\n\u001b[0;32m      4\u001b[0m       steps_per_epoch\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m12\u001b[39m,\n\u001b[0;32m      5\u001b[0m       epochs\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m100\u001b[39m,\n\u001b[0;32m      6\u001b[0m       validation_data\u001b[38;5;241m=\u001b[39mvalidation_generator,\n\u001b[0;32m      7\u001b[0m       validation_steps\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m9\u001b[39m)\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\keras\\src\\engine\\training.py:2889\u001b[0m, in \u001b[0;36mModel.fit_generator\u001b[1;34m(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, validation_freq, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch)\u001b[0m\n\u001b[0;32m   2877\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Fits the model on data yielded batch-by-batch by a Python generator.\u001b[39;00m\n\u001b[0;32m   2878\u001b[0m \n\u001b[0;32m   2879\u001b[0m \u001b[38;5;124;03mDEPRECATED:\u001b[39;00m\n\u001b[0;32m   2880\u001b[0m \u001b[38;5;124;03m  `Model.fit` now supports generators, so there is no longer any need to\u001b[39;00m\n\u001b[0;32m   2881\u001b[0m \u001b[38;5;124;03m  use this endpoint.\u001b[39;00m\n\u001b[0;32m   2882\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m   2883\u001b[0m warnings\u001b[38;5;241m.\u001b[39mwarn(\n\u001b[0;32m   2884\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`Model.fit_generator` is deprecated and \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   2885\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwill be removed in a future version. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   2886\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPlease use `Model.fit`, which supports generators.\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m   2887\u001b[0m     stacklevel\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m2\u001b[39m,\n\u001b[0;32m   2888\u001b[0m )\n\u001b[1;32m-> 2889\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfit(\n\u001b[0;32m   2890\u001b[0m     generator,\n\u001b[0;32m   2891\u001b[0m     steps_per_epoch\u001b[38;5;241m=\u001b[39msteps_per_epoch,\n\u001b[0;32m   2892\u001b[0m     epochs\u001b[38;5;241m=\u001b[39mepochs,\n\u001b[0;32m   2893\u001b[0m     verbose\u001b[38;5;241m=\u001b[39mverbose,\n\u001b[0;32m   2894\u001b[0m     callbacks\u001b[38;5;241m=\u001b[39mcallbacks,\n\u001b[0;32m   2895\u001b[0m     validation_data\u001b[38;5;241m=\u001b[39mvalidation_data,\n\u001b[0;32m   2896\u001b[0m     validation_steps\u001b[38;5;241m=\u001b[39mvalidation_steps,\n\u001b[0;32m   2897\u001b[0m     validation_freq\u001b[38;5;241m=\u001b[39mvalidation_freq,\n\u001b[0;32m   2898\u001b[0m     class_weight\u001b[38;5;241m=\u001b[39mclass_weight,\n\u001b[0;32m   2899\u001b[0m     max_queue_size\u001b[38;5;241m=\u001b[39mmax_queue_size,\n\u001b[0;32m   2900\u001b[0m     workers\u001b[38;5;241m=\u001b[39mworkers,\n\u001b[0;32m   2901\u001b[0m     use_multiprocessing\u001b[38;5;241m=\u001b[39muse_multiprocessing,\n\u001b[0;32m   2902\u001b[0m     shuffle\u001b[38;5;241m=\u001b[39mshuffle,\n\u001b[0;32m   2903\u001b[0m     initial_epoch\u001b[38;5;241m=\u001b[39minitial_epoch,\n\u001b[0;32m   2904\u001b[0m )\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\keras\\src\\utils\\traceback_utils.py:65\u001b[0m, in \u001b[0;36mfilter_traceback.<locals>.error_handler\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m     63\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m     64\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m---> 65\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m fn(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m     66\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m     67\u001b[0m     filtered_tb \u001b[38;5;241m=\u001b[39m _process_traceback_frames(e\u001b[38;5;241m.\u001b[39m__traceback__)\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\keras\\src\\engine\\training.py:1832\u001b[0m, in \u001b[0;36mModel.fit\u001b[1;34m(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)\u001b[0m\n\u001b[0;32m   1816\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mgetattr\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m_eval_data_handler\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m) \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m   1817\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_eval_data_handler \u001b[38;5;241m=\u001b[39m data_adapter\u001b[38;5;241m.\u001b[39mget_data_handler(\n\u001b[0;32m   1818\u001b[0m         x\u001b[38;5;241m=\u001b[39mval_x,\n\u001b[0;32m   1819\u001b[0m         y\u001b[38;5;241m=\u001b[39mval_y,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   1830\u001b[0m         pss_evaluation_shards\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_pss_evaluation_shards,\n\u001b[0;32m   1831\u001b[0m     )\n\u001b[1;32m-> 1832\u001b[0m val_logs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mevaluate(\n\u001b[0;32m   1833\u001b[0m     x\u001b[38;5;241m=\u001b[39mval_x,\n\u001b[0;32m   1834\u001b[0m     y\u001b[38;5;241m=\u001b[39mval_y,\n\u001b[0;32m   1835\u001b[0m     sample_weight\u001b[38;5;241m=\u001b[39mval_sample_weight,\n\u001b[0;32m   1836\u001b[0m     batch_size\u001b[38;5;241m=\u001b[39mvalidation_batch_size \u001b[38;5;129;01mor\u001b[39;00m batch_size,\n\u001b[0;32m   1837\u001b[0m     steps\u001b[38;5;241m=\u001b[39mvalidation_steps,\n\u001b[0;32m   1838\u001b[0m     callbacks\u001b[38;5;241m=\u001b[39mcallbacks,\n\u001b[0;32m   1839\u001b[0m     max_queue_size\u001b[38;5;241m=\u001b[39mmax_queue_size,\n\u001b[0;32m   1840\u001b[0m     workers\u001b[38;5;241m=\u001b[39mworkers,\n\u001b[0;32m   1841\u001b[0m     use_multiprocessing\u001b[38;5;241m=\u001b[39muse_multiprocessing,\n\u001b[0;32m   1842\u001b[0m     return_dict\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[0;32m   1843\u001b[0m     _use_cached_eval_dataset\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[0;32m   1844\u001b[0m )\n\u001b[0;32m   1845\u001b[0m val_logs \u001b[38;5;241m=\u001b[39m {\n\u001b[0;32m   1846\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mval_\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m name: val \u001b[38;5;28;01mfor\u001b[39;00m name, val \u001b[38;5;129;01min\u001b[39;00m val_logs\u001b[38;5;241m.\u001b[39mitems()\n\u001b[0;32m   1847\u001b[0m }\n\u001b[0;32m   1848\u001b[0m epoch_logs\u001b[38;5;241m.\u001b[39mupdate(val_logs)\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\keras\\src\\utils\\traceback_utils.py:65\u001b[0m, in \u001b[0;36mfilter_traceback.<locals>.error_handler\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m     63\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m     64\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m---> 65\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m fn(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m     66\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m     67\u001b[0m     filtered_tb \u001b[38;5;241m=\u001b[39m _process_traceback_frames(e\u001b[38;5;241m.\u001b[39m__traceback__)\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\keras\\src\\engine\\training.py:2272\u001b[0m, in \u001b[0;36mModel.evaluate\u001b[1;34m(self, x, y, batch_size, verbose, sample_weight, steps, callbacks, max_queue_size, workers, use_multiprocessing, return_dict, **kwargs)\u001b[0m\n\u001b[0;32m   2268\u001b[0m             \u001b[38;5;28;01mwith\u001b[39;00m tf\u001b[38;5;241m.\u001b[39mprofiler\u001b[38;5;241m.\u001b[39mexperimental\u001b[38;5;241m.\u001b[39mTrace(\n\u001b[0;32m   2269\u001b[0m                 \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtest\u001b[39m\u001b[38;5;124m\"\u001b[39m, step_num\u001b[38;5;241m=\u001b[39mstep, _r\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m\n\u001b[0;32m   2270\u001b[0m             ):\n\u001b[0;32m   2271\u001b[0m                 callbacks\u001b[38;5;241m.\u001b[39mon_test_batch_begin(step)\n\u001b[1;32m-> 2272\u001b[0m                 logs \u001b[38;5;241m=\u001b[39m test_function_runner\u001b[38;5;241m.\u001b[39mrun_step(\n\u001b[0;32m   2273\u001b[0m                     dataset_or_iterator,\n\u001b[0;32m   2274\u001b[0m                     data_handler,\n\u001b[0;32m   2275\u001b[0m                     step,\n\u001b[0;32m   2276\u001b[0m                     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_pss_evaluation_shards,\n\u001b[0;32m   2277\u001b[0m                 )\n\u001b[0;32m   2279\u001b[0m logs \u001b[38;5;241m=\u001b[39m tf_utils\u001b[38;5;241m.\u001b[39msync_to_numpy_or_python_type(logs)\n\u001b[0;32m   2280\u001b[0m \u001b[38;5;66;03m# Override with model metrics instead of last step logs\u001b[39;00m\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\keras\\src\\engine\\training.py:4079\u001b[0m, in \u001b[0;36m_TestFunction.run_step\u001b[1;34m(self, dataset_or_iterator, data_handler, step, unused_shards)\u001b[0m\n\u001b[0;32m   4078\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mrun_step\u001b[39m(\u001b[38;5;28mself\u001b[39m, dataset_or_iterator, data_handler, step, unused_shards):\n\u001b[1;32m-> 4079\u001b[0m     tmp_logs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_function(dataset_or_iterator)\n\u001b[0;32m   4080\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m data_handler\u001b[38;5;241m.\u001b[39mshould_sync:\n\u001b[0;32m   4081\u001b[0m         context\u001b[38;5;241m.\u001b[39masync_wait()\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\tensorflow\\python\\util\\traceback_utils.py:150\u001b[0m, in \u001b[0;36mfilter_traceback.<locals>.error_handler\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m    148\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m    149\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 150\u001b[0m   \u001b[38;5;28;01mreturn\u001b[39;00m fn(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m    151\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m    152\u001b[0m   filtered_tb \u001b[38;5;241m=\u001b[39m _process_traceback_frames(e\u001b[38;5;241m.\u001b[39m__traceback__)\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\polymorphic_function.py:831\u001b[0m, in \u001b[0;36mFunction.__call__\u001b[1;34m(self, *args, **kwds)\u001b[0m\n\u001b[0;32m    828\u001b[0m compiler \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mxla\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_jit_compile \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnonXla\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m    830\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m OptionalXlaContext(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_jit_compile):\n\u001b[1;32m--> 831\u001b[0m   result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwds)\n\u001b[0;32m    833\u001b[0m new_tracing_count \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexperimental_get_tracing_count()\n\u001b[0;32m    834\u001b[0m without_tracing \u001b[38;5;241m=\u001b[39m (tracing_count \u001b[38;5;241m==\u001b[39m new_tracing_count)\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\polymorphic_function.py:876\u001b[0m, in \u001b[0;36mFunction._call\u001b[1;34m(self, *args, **kwds)\u001b[0m\n\u001b[0;32m    873\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_lock\u001b[38;5;241m.\u001b[39mrelease()\n\u001b[0;32m    874\u001b[0m \u001b[38;5;66;03m# In this case we have not created variables on the first call. So we can\u001b[39;00m\n\u001b[0;32m    875\u001b[0m \u001b[38;5;66;03m# run the first trace but we should fail if variables are created.\u001b[39;00m\n\u001b[1;32m--> 876\u001b[0m results \u001b[38;5;241m=\u001b[39m tracing_compilation\u001b[38;5;241m.\u001b[39mcall_function(\n\u001b[0;32m    877\u001b[0m     args, kwds, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_variable_creation_config\n\u001b[0;32m    878\u001b[0m )\n\u001b[0;32m    879\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_created_variables:\n\u001b[0;32m    880\u001b[0m   \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCreating variables on a non-first call to a function\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m    881\u001b[0m                    \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m decorated with tf.function.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\tracing_compilation.py:139\u001b[0m, in \u001b[0;36mcall_function\u001b[1;34m(args, kwargs, tracing_options)\u001b[0m\n\u001b[0;32m    137\u001b[0m bound_args \u001b[38;5;241m=\u001b[39m function\u001b[38;5;241m.\u001b[39mfunction_type\u001b[38;5;241m.\u001b[39mbind(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m    138\u001b[0m flat_inputs \u001b[38;5;241m=\u001b[39m function\u001b[38;5;241m.\u001b[39mfunction_type\u001b[38;5;241m.\u001b[39munpack_inputs(bound_args)\n\u001b[1;32m--> 139\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m function\u001b[38;5;241m.\u001b[39m_call_flat(  \u001b[38;5;66;03m# pylint: disable=protected-access\u001b[39;00m\n\u001b[0;32m    140\u001b[0m     flat_inputs, captured_inputs\u001b[38;5;241m=\u001b[39mfunction\u001b[38;5;241m.\u001b[39mcaptured_inputs\n\u001b[0;32m    141\u001b[0m )\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\concrete_function.py:1264\u001b[0m, in \u001b[0;36mConcreteFunction._call_flat\u001b[1;34m(self, tensor_inputs, captured_inputs)\u001b[0m\n\u001b[0;32m   1260\u001b[0m possible_gradient_type \u001b[38;5;241m=\u001b[39m gradients_util\u001b[38;5;241m.\u001b[39mPossibleTapeGradientTypes(args)\n\u001b[0;32m   1261\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (possible_gradient_type \u001b[38;5;241m==\u001b[39m gradients_util\u001b[38;5;241m.\u001b[39mPOSSIBLE_GRADIENT_TYPES_NONE\n\u001b[0;32m   1262\u001b[0m     \u001b[38;5;129;01mand\u001b[39;00m executing_eagerly):\n\u001b[0;32m   1263\u001b[0m   \u001b[38;5;66;03m# No tape is watching; skip to running the function.\u001b[39;00m\n\u001b[1;32m-> 1264\u001b[0m   \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_inference_function\u001b[38;5;241m.\u001b[39mflat_call(args)\n\u001b[0;32m   1265\u001b[0m forward_backward \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_select_forward_and_backward_functions(\n\u001b[0;32m   1266\u001b[0m     args,\n\u001b[0;32m   1267\u001b[0m     possible_gradient_type,\n\u001b[0;32m   1268\u001b[0m     executing_eagerly)\n\u001b[0;32m   1269\u001b[0m forward_function, args_with_tangents \u001b[38;5;241m=\u001b[39m forward_backward\u001b[38;5;241m.\u001b[39mforward()\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\atomic_function.py:217\u001b[0m, in \u001b[0;36mAtomicFunction.flat_call\u001b[1;34m(self, args)\u001b[0m\n\u001b[0;32m    215\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mflat_call\u001b[39m(\u001b[38;5;28mself\u001b[39m, args: Sequence[core\u001b[38;5;241m.\u001b[39mTensor]) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any:\n\u001b[0;32m    216\u001b[0m \u001b[38;5;250m  \u001b[39m\u001b[38;5;124;03m\"\"\"Calls with tensor inputs and returns the structured output.\"\"\"\u001b[39;00m\n\u001b[1;32m--> 217\u001b[0m   flat_outputs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m(\u001b[38;5;241m*\u001b[39margs)\n\u001b[0;32m    218\u001b[0m   \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfunction_type\u001b[38;5;241m.\u001b[39mpack_output(flat_outputs)\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\atomic_function.py:252\u001b[0m, in \u001b[0;36mAtomicFunction.__call__\u001b[1;34m(self, *args)\u001b[0m\n\u001b[0;32m    250\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m record\u001b[38;5;241m.\u001b[39mstop_recording():\n\u001b[0;32m    251\u001b[0m   \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_bound_context\u001b[38;5;241m.\u001b[39mexecuting_eagerly():\n\u001b[1;32m--> 252\u001b[0m     outputs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_bound_context\u001b[38;5;241m.\u001b[39mcall_function(\n\u001b[0;32m    253\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mname,\n\u001b[0;32m    254\u001b[0m         \u001b[38;5;28mlist\u001b[39m(args),\n\u001b[0;32m    255\u001b[0m         \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfunction_type\u001b[38;5;241m.\u001b[39mflat_outputs),\n\u001b[0;32m    256\u001b[0m     )\n\u001b[0;32m    257\u001b[0m   \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m    258\u001b[0m     outputs \u001b[38;5;241m=\u001b[39m make_call_op_in_graph(\n\u001b[0;32m    259\u001b[0m         \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m    260\u001b[0m         \u001b[38;5;28mlist\u001b[39m(args),\n\u001b[0;32m    261\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_bound_context\u001b[38;5;241m.\u001b[39mfunction_call_options\u001b[38;5;241m.\u001b[39mas_attrs(),\n\u001b[0;32m    262\u001b[0m     )\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\tensorflow\\python\\eager\\context.py:1479\u001b[0m, in \u001b[0;36mContext.call_function\u001b[1;34m(self, name, tensor_inputs, num_outputs)\u001b[0m\n\u001b[0;32m   1477\u001b[0m cancellation_context \u001b[38;5;241m=\u001b[39m cancellation\u001b[38;5;241m.\u001b[39mcontext()\n\u001b[0;32m   1478\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m cancellation_context \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m-> 1479\u001b[0m   outputs \u001b[38;5;241m=\u001b[39m execute\u001b[38;5;241m.\u001b[39mexecute(\n\u001b[0;32m   1480\u001b[0m       name\u001b[38;5;241m.\u001b[39mdecode(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mutf-8\u001b[39m\u001b[38;5;124m\"\u001b[39m),\n\u001b[0;32m   1481\u001b[0m       num_outputs\u001b[38;5;241m=\u001b[39mnum_outputs,\n\u001b[0;32m   1482\u001b[0m       inputs\u001b[38;5;241m=\u001b[39mtensor_inputs,\n\u001b[0;32m   1483\u001b[0m       attrs\u001b[38;5;241m=\u001b[39mattrs,\n\u001b[0;32m   1484\u001b[0m       ctx\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   1485\u001b[0m   )\n\u001b[0;32m   1486\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m   1487\u001b[0m   outputs \u001b[38;5;241m=\u001b[39m execute\u001b[38;5;241m.\u001b[39mexecute_with_cancellation(\n\u001b[0;32m   1488\u001b[0m       name\u001b[38;5;241m.\u001b[39mdecode(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mutf-8\u001b[39m\u001b[38;5;124m\"\u001b[39m),\n\u001b[0;32m   1489\u001b[0m       num_outputs\u001b[38;5;241m=\u001b[39mnum_outputs,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   1493\u001b[0m       cancellation_manager\u001b[38;5;241m=\u001b[39mcancellation_context,\n\u001b[0;32m   1494\u001b[0m   )\n",
      "File \u001b[1;32m~\\anaconda3\\Lib\\site-packages\\tensorflow\\python\\eager\\execute.py:60\u001b[0m, in \u001b[0;36mquick_execute\u001b[1;34m(op_name, num_outputs, inputs, attrs, ctx, name)\u001b[0m\n\u001b[0;32m     53\u001b[0m   \u001b[38;5;66;03m# Convert any objects of type core_types.Tensor to Tensor.\u001b[39;00m\n\u001b[0;32m     54\u001b[0m   inputs \u001b[38;5;241m=\u001b[39m [\n\u001b[0;32m     55\u001b[0m       tensor_conversion_registry\u001b[38;5;241m.\u001b[39mconvert(t)\n\u001b[0;32m     56\u001b[0m       \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(t, core_types\u001b[38;5;241m.\u001b[39mTensor)\n\u001b[0;32m     57\u001b[0m       \u001b[38;5;28;01melse\u001b[39;00m t\n\u001b[0;32m     58\u001b[0m       \u001b[38;5;28;01mfor\u001b[39;00m t \u001b[38;5;129;01min\u001b[39;00m inputs\n\u001b[0;32m     59\u001b[0m   ]\n\u001b[1;32m---> 60\u001b[0m   tensors \u001b[38;5;241m=\u001b[39m pywrap_tfe\u001b[38;5;241m.\u001b[39mTFE_Py_Execute(ctx\u001b[38;5;241m.\u001b[39m_handle, device_name, op_name,\n\u001b[0;32m     61\u001b[0m                                       inputs, attrs, num_outputs)\n\u001b[0;32m     62\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m core\u001b[38;5;241m.\u001b[39m_NotOkStatusException \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m     63\u001b[0m   \u001b[38;5;28;01mif\u001b[39;00m name \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "# define model\n",
    "history = model.fit_generator(\n",
    "      train_generator,\n",
    "      steps_per_epoch=12,\n",
    "      epochs=100,\n",
    "      validation_data=validation_generator,\n",
    "      validation_steps=9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d9dc8b61",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e20b31d6",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ee267bdf",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "cbdce7fb",
   "metadata": {},
   "outputs": [],
   "source": [
    "#save model\n",
    "model_json=model.to_json()\n",
    "with open(\"vgg19-swish-Adagrad.json\", \"w\") as json_file:\n",
    "    json_file.write(model_json)\n",
    "#serializar los pesos\n",
    "model.save_weights(\"vgg19-swish-Adagrad.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "b05790e8",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\oscar\\AppData\\Local\\Temp\\ipykernel_28248\\1979981568.py:1: UserWarning: `Model.predict_generator` is deprecated and will be removed in a future version. Please use `Model.predict`, which supports generators.\n",
      "  predictions=model.predict_generator(validation_generator, steps=len(validation_generator), verbose=1)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9/9 [==============================] - 9s 952ms/step\n"
     ]
    }
   ],
   "source": [
    "predictions=model.predict_generator(validation_generator, steps=len(validation_generator), verbose=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "30f61bd8",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "val_preds = np.round(predictions)# from probabilities to 0 or 1\n",
    "val_trues = validation_generator.classes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "815d8a65",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\oscar\\AppData\\Local\\Temp\\ipykernel_28248\\3852048864.py:7: UserWarning: `Model.predict_generator` is deprecated and will be removed in a future version. Please use `Model.predict`, which supports generators.\n",
      "  Y_pred = model.predict_generator(validation_generator, num_of_test_samples // batch_size+1)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Confusion Matrix\n",
      "[[14  6  4  2]\n",
      " [ 2 54  6  0]\n",
      " [ 0  7 27  2]\n",
      " [ 1  8  6 24]]\n"
     ]
    }
   ],
   "source": [
    "#modify:\n",
    "from sklearn.metrics import confusion_matrix\n",
    "from sklearn.metrics import classification_report\n",
    "import numpy as np\n",
    "num_of_test_samples = 163 #number of testing samples\n",
    "batch_size=20 #batch size for the validation set\n",
    "Y_pred = model.predict_generator(validation_generator, num_of_test_samples // batch_size+1)\n",
    "y_pred = np.argmax(Y_pred, axis=1)\n",
    "print('Confusion Matrix')\n",
    "print(confusion_matrix(validation_generator.classes, y_pred))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "fcd5652d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Classification Report\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "        croc       0.82      0.54      0.65        26\n",
      "       hyena       0.72      0.87      0.79        62\n",
      "     leopard       0.63      0.75      0.68        36\n",
      "        lion       0.86      0.62      0.72        39\n",
      "\n",
      "    accuracy                           0.73       163\n",
      "   macro avg       0.76      0.69      0.71       163\n",
      "weighted avg       0.75      0.73      0.73       163\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print('Classification Report')\n",
    "target_names = [ \"croc\",'hyena', 'leopard', 'lion']\n",
    "print(classification_report(validation_generator.classes, y_pred, target_names=target_names))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6f8f01c0",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad6ed72d",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "34cbf1e7",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "9e82b384",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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uDHuuusuTJ8+HUIIVK1aFZ9//jmSkpJsjtmiRQsAwBtvvIExY8bAz88PjRo1sph7ohg9ejTefvttjBkzBufOnUOLFi2wb98+vPLKK+jXr5/FapbCGDBgABITE/Hkk09iyJAhuHDhAl5++WVERETg9OnTxnpxcXEYNWoU5s2bhz/++AMDBgxAQEAAUlNTUaFCBTz99NOoW7cu/v3vf+Pll1/G7du3MXz4cISGhuL48eO4cuUK5syZAwAYNWoURo4ciSeffBKDBw/G+fPn8frrrxt7aNS2W83v6fDhw7Fy5UpMmDABJ0+eRI8ePVBQUIDvv/8eTZo0wUMPPWSs27BhQ/Tp0wc7duzAPffcYzN/icoB7875JXLO0SqhZs2a2a2/f/9+0alTJ1GhQgVRo0YNMX78ePHjjz/arMBxtEqof//+Nsd0tDrCepWQdTsdnSc9PV3Ex8eL4OBgUalSJTF48GCxfft2m1Ur9uTm5opnn31W1K5dWwQGBoq2bduKTz/91GZljbJK6D//+Y/NMQCIWbNmWZS9//77okGDBsLf3180bNhQrFixwu5qHWdGjBghAIguXbrY3f7555+LVq1aicDAQFG7dm3x3HPPiR07dti9lq5WCQkhxPHjx8V9990nAgMDRdWqVcW4cePEZ599ZnM8pV6lSpVElSpVxIMPPijS09PtXocZM2aIWrVqCR8fH4vjWP8OCCHE1atXxYQJE0RERITw9fUV0dHRYsaMGSInJ8eiHgDx1FNP2VwPR6txrL366quibt26IiAgQDRp0kS89957dn+vDAaDWLx4sWjevLnw9/cXoaGholOnTuLzzz+3qLd69Wpx9913i8DAQBEcHCzatGlj8W+joKBAvP7666JevXoiMDBQtGvXTuzevdvhv4NPPvnEps1qf0+FkCvxXnrpJePvX7Vq1cS9994r9u/fb3PcVatWCQBiw4YNLq8blT06Iayy8RBRsXvllVfwwgsvID093eOTIonKisGDB+O7777DuXPn4Ofn5+3mUDHjkBBRMfvf//4HQA5X3LlzB7t378abb76JkSNHMlghspKbm4sff/wRBw8exJYtW7Bo0SIGK+UUAxaiYlahQgUsXrwY586dQ25uLurUqYPnn38eL7zwgrebRlTiZGRkoHPnzggJCcETTzyBp59+2ttNIi/hkBARERGVeFzWTERERCUe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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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znpTTwSaE56+4xtapmbNmuGJJ57A2rVr8corr2Dt2rXw9/dHr169tNts2bIFmZmZiImJ0bYWADB5kKC3t7dBZT579ixOnz6NdevWISIiQrv+0qVLJh238PGPHj0KIYTOa/HWrVvIy8tDjRo1yrX/klSvXh02NjZITU0tdt+NGzcAQHtsV1dXLFiwAAsWLMBff/2lbb0YOHAgLly4AEC2TH311VcAgD/++APff/89IiMjkZOTg88//7xCngM9HthiQVZB8wav+VSu8a9//asyiqNXWFgYHjx4gB07duis13zaL4tKpSr2/M6cOVNs/g9DNW7cGH5+ftiwYQOEENr1V69exaFDhwzez7hx43D06FEcPHgQ27ZtQ0REhE4XjL6/jRACa9asMancXbt2xblz53D69Gmd9evXr9e5bcxromhrTmm6d++OjIwMbNmyRWe95mqa7t27l7kPU7i6uqJDhw6IiYnRKadarca3336LgIAANGrUqNjjatWqhbFjx2LEiBFITExEVlZWsW0aNWqEd955By1btsTJkycrpPz0+GCLBVmFjh07onr16pg0aRLmz58Pe3t7fPfdd8VOPpUpIiICy5cvx+jRo7F48WI0aNAAO3bswC+//AIAZV6FMWDAACxatAjz589HWFgYEhMTsXDhQgQHByMvL8/o8tjY2GDRokWYOHEinn32Wbz00ku4f/8+IiMjDe4KAeQYkZkzZ2LEiBHIzs4udmloz5494eDggBEjRmD27Nl49OgRVq9ejXv37hldZgCYMWMGvv76a/Tv3x+LFy/WXhWi+SSu0aRJE9SvXx9z586FEAJeXl7Ytm0bdu3aVWyfLVu2BAB88skniIiIgL29PRo3bqwzNkJjzJgxWLlyJSIiIpCcnIyWLVvi4MGDeP/999GvXz+dK2SUFhUVhZ49e6Jr165444034ODggFWrVuHs2bPYsGGDNkx16NABAwYMQEhICKpXr47z58/jm2++wVNPPQUXFxecOXMGU6ZMwbBhw9CwYUM4ODhg7969OHPmDObOnVth5afHA1ssyCp4e3tj+/btcHFxwejRozF+/Hi4ublh06ZNlV00LVdXV+zduxfh4eGYPXs2nnvuOaSkpGhndiw642NR8+bNw6xZs/DVV1+hf//++PLLL/H555+jc+fOJpdpwoQJ+PLLL/H7779jyJAhWLhwId5+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p6dnmedvo1os/Pz80KxZM511TZs2RUpKSomPcXR0hIeHh85CRERE1smoYNGpUyckJibqrPvjjz8QFBSkaKGIiIjIMhkVLF5//XUcOXIE77//Pi5duoT169fjiy++wOTJkyuqfERERGRBjAoW7du3x+bNm7Fhwwa0aNECixYtwooVKzBq1KiKKh8RERFZEKMGbyrB0MEfREREVHVUyOBNIiIiotIwWBAREZFiGCyIiIhIMQwWREREpBgGCyIiIlIMgwUREREphsGCiIiIFMNgQURERIphsCAiIiLFMFgQERGRYhgsiIiISDEMFkRERKQYBgsiIiJSDIMFERERKYbBgoiIiBTDYEFERESKYbAgIiIixTBYEBERkWIYLIiIiEgxDBZERESkGAYLIiIiUgyDBRERESmGwYKIiIgUw2BBREREimGwICIiIsUwWBAREZFiGCyIiIhIMQwWREREpBgGCyIiIlIMgwUREREphsGCiIiIFMNgQURERIphsCAiIiLFMFgQERGRYhgsiIiISDEMFkRERKQYBgsiIiJSDIMFERERKYbBgoiIiBRjVLCIjIyESqXSWXx9fSuqbERERGRh7Ix9QPPmzbF7927tbVtbW0ULRERERJbL6GBhZ2dnVCtFdnY2srOztbfT09ONPSQRERFZCKPHWFy8eBH+/v4IDg7GCy+8gCtXrpS6fVRUFDw9PbVLYGCgyYUlIiKiqk0lhBCGbrxjxw5kZWWhUaNG+Ouvv7B48WJcuHAB586dg7e3t97H6GuxCAwMRFpaGjw8PMr/DIiIiKjCpaenw9PTs8zzt1HBoqjMzEzUr18fs2fPxsyZMxUtGBEREVUdhp6/y3W5qaurK1q2bImLFy+WZzdERERkJcoVLLKzs3H+/Hn4+fkpVR4iIiKyYEYFizfeeAP79u1DUlISjh49iqFDhyI9PR0REREVVT4iIiKyIEZdbvrnn39ixIgRuHPnDmrWrIknn3wSR44cQVBQUEWVj4iIiCyIUcFi48aNFVUOIiIisgL8rhAiIiJSDIMFERERKYbBgoiIiBTDYEFERESKYbAgIiIixTBYEBERkWIYLIiIiEgxDBZERESkGAYLIiIiUgyDBRERESmGwYKIiIgUw2BBREREimGwICIiIsUwWBAREZFiGCyIiIhIMQwWREREpBgGCyIiIlIMgwUREREphsGCiIiIFMNgQURERIphsCAiIiLFMFgQERGRYhgsiIiISDEMFkRERKQYBgsiIiJSDIMFERERKYbBgoiIiBTDYEFERESKYbAgIiIixTBYEBERkWIYLIiIiEgxDBZERESkGAYLIiIiUgyDBRERESmGwYKIiIgUw2BBREREimGwICIiIsUwWBAREZFiyhUsoqKioFKpMGPGDIWKQ0RERJbM5GBx/PhxfPHFFwgJCVGyPERERGTBTAoWGRkZGDVqFNasWYPq1asrXSYiIiKyUCYFi8mTJ6N///7o0aNHmdtmZ2cjPT1dZyEiIiLrZGfsAzZu3IiTJ0/i+PHjBm0fFRWFBQsWGF0wIiIisjxGtVhcu3YN06dPx7fffgsnJyeDHvPWW28hLS1Nu1y7ds2kghIREVHVpxJCCEM33rJlC5599lnY2tpq1+Xn50OlUsHGxgbZ2dk69+mTnp4OT09PpKWlwcPDw/SSExERkdkYev42qiuke/fuSEhI0Fk3btw4NGnSBHPmzCkzVBAREZF1MypYuLu7o0WLFjrrXF1d4e3tXWw9ERERPX448yYREREpxuirQoqKi4tToBhERERkDdhiQURERIphsCAiIiLFMFgQERGRYhgsiIiISDEMFkRERKQYBgsiIiJSDIMFERERKYbBgoiIiBTDYEFERESKYbAgIiIixTBYEBERkWIYLIiIiEgxDBZERESkGAYLIiIiUgyDBRERESmGwYKIiIgUw2BBREREimGwICIiIsUwWBAREZFiGCyIiIhIMQwWREREpBgGCyIiIlIMgwUREREphsGCiIiIFMNgQURERIphsCAiIiLFMFgQERGRYhgsiIiISDEMFkRERKQYBgsiIiJSDIMFERERKYbBgoiIiBTDYEFERESKYbAgIiIixTBYEBERkWIYLIiIiEgxDBZERESkGAYLIiIiUgyDBRERESnGqGCxevVqhISEwMPDAx4eHnjqqaewY8eOiiobERERWRijgkVAQAA++OAD/Pbbb/jtt9/QrVs3DBo0COfOnauo8hEREZEFUQkhRHl24OXlhY8//hgTJkwwaPv09HR4enoiLS0NHh4e5Tk0ERERmYmh5287Uw+Qn5+PH374AZmZmXjqqadK3C47OxvZ2dk6BSMiIiLrZPTgzYSEBLi5ucHR0RGTJk3C5s2b0axZsxK3j4qKgqenp3YJDAwsV4GJiIio6jK6KyQnJwcpKSm4f/8+oqOj8eWXX2Lfvn0lhgt9LRaBgYHsCiEiIrIghnaFlHuMRY8ePVC/fn3861//UrRgREREVHUYev4u9zwWQgidFgkiIiJ6fBk1ePPtt99G3759ERgYiAcPHmDjxo2Ii4vDzp07K6p8REREZEGMChZ//fUXXnzxRaSmpsLT0xMhISHYuXMnevbsWVHlIyIiIgtiVLD46quvKqocREREZAX4XSFERESkGAYLIiIiUgyDBRERESmGwYKIiIgUw2BBREREimGwICIiIsUwWBAREZFiGCyIiIhIMQwWREREpBgGCyIiIlIMgwUREREphsGCiIiIFMNgQURERIphsCAiIiLFMFgQERGRYhgsiIiISDEMFkRERKQYBgsiIiJSDIMFERERKYbBgoiIiBTDYEFERESKYbAgIiIixTBYEBERkWIYLIiIiEgxDBZERESkGAYLIiIiUgyDBRERESmGwYKIiIgUw2BBREREimGwICIiIsUwWBAREZFiGCyIiIhIMQwWREREpBgGCyIiIlIMgwUREREphsGCiIiIFMNgQURERIphsCAiIiLFGBUsoqKi0L59e7i7u8PHxweDBw9GYmJiRZWNiIiILIxRwWLfvn2YPHkyjhw5gl27diEvLw+9evVCZmZmRZWPiIiILIhKCCFMffDt27fh4+ODffv2oUuXLgY9Jj09HZ6enkhLS4OHh4ephyYiIiIzMvT8bVeeg6SlpQEAvLy8StwmOzsb2dnZOgUjIiIi62Ty4E0hBGbOnInOnTujRYsWJW4XFRUFT09P7RIYGGjqIYmIiKiKM7krZPLkydi+fTsOHjyIgICAErfT12IRGBjIrhAiIiILUqFdIVOnTsXWrVuxf//+UkMFADg6OsLR0dGUwxAREZGFMSpYCCEwdepUbN68GXFxcQgODq6ochEREZEFMipYTJ48GevXr8d///tfuLu74+bNmwAAT09PODs7V0gBiYiIyHIYNcZCpVLpXb927VqMHTvWoH3wclMiIiLLUyFjLMox5QURERE9BvhdIURERKQYBgsiIiJSTLlm3qzK8vOBAweA1FTAzw94+mnA1rayS0VERGTdrDJYxMQA06cDf/5ZsC4gAPjkE2DIkMorFxERkbWzuq6QmBhg6FDdUAEA16/L9TExlVMuIiKix4FVBIv8fODXX4GPPwamTQP0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586d0aJFCwDQ1q2+er969arZy2jpNm7ciJMnT+L48ePF7mNdK+vKlStYvXo1Zs6cibfffhvHjh3DtGnT4OjoiDFjxrC+FTRnzhykpaWhSZMmsLW1RX5+PpYsWYIRI0YA4Gu7ohhSrzdv3oSDgwOqV69ebJvynjstPlhoqFQqndtCiGLryDRTpkzBmTNncPDgwWL3sd7L79q1a5g+fTp+/fVXODk5lbgd61oZarUa7dq1w/vvvw8AaN26Nc6dO4fVq1djzJgx2u1Y3+W3adMmfPvtt1i/fj2aN2+O+Ph4zJgxA/7+/oiIiNBux7quGKbUqxJ1b/FdITVq1ICtrW2xhHXr1q1iaY2MN3XqVGzduhWxsbEICAjQrvf19QUA1rsCTpw4gVu3bqFt27aws7ODnZ0d9u3bh08//RR2dnba+mRdK8PPzw/NmjXTWde0aVOkpKQA4GtbSW+++Sbmzp2LF154AS1btsSLL76I119/HVFRUQBY1xXFkHr19fVFTk4O7t27V+I2prL4YOHg4IC2bdti165dOut37dqFjh07VlKpLJ8QAlOmTEFMTAz27t2L4OBgnfuDg4Ph6+urU+85OTnYt28f691I3bt3R0JCAuLj47VLu3btMGrUKMTHx6NevXqsawV16tSp2KXTf/zxB4KCggDwta2krKws2NjonmZsbW21l5uyriuGIfXatm1b2Nvb62yTmpqKs2fPlr/uyzX0s4rQXG761Vdfid9//13MmDFDuLq6iuTk5MoumsV69dVXhaenp4iLixOpqanaJSsrS7vNBx98IDw9PUVMTIxISEgQI0aM4GViCil8VYgQrGslHTt2TNjZ2YklS5aIixcviu+++064uLiIb7/9VrsN61sZERERonbt2trLTWNiYkSNGjXE7Nmztduwrk3z4MEDcerUKXHq1CkBQCxbtkycOnVKO82CIfU6adIkERAQIHbv3i1OnjwpunXrxstNC1u5cqUICgoSDg4Ook2bNtrLIsk0APQua9eu1W6jVqvF/Pnzha+vr3B0dBRdunQRCQkJlVdoK1I0WLCulbVt2zbRokUL4ejoKJo0aSK++OILnftZ38pIT08X06dPF3Xq1BFOTk6iXr16Yt68eSI7O1u7DevaNLGxsXrfoyMiIoQQhtXrw4cPxZQpU4SXl5dwdnYWAwYMECkpKeUum0oIIcrX5kFEREQkWfwYCyIiIqo6GCyIiIhIMQwWREREpBgGCyIiIlIMgwUREREphsGCiIiIFMNgQURERIphsCAiIiLFMFgQERGRYhgsiIiISDEMFkRERKSY/wPQdV9auK2VKwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "#PLOT\n",
    "acc = history.history['accuracy']\n",
    "val_acc = history.history['val_accuracy']\n",
    "loss = history.history['loss']\n",
    "val_loss = history.history['val_loss']\n",
    "\n",
    "epochs = range(len(acc))\n",
    "\n",
    "plt.plot(epochs, acc, 'bo', label='Training acc')\n",
    "plt.plot(epochs, val_acc, 'b', label='Validation acc')\n",
    "plt.title('Training and validation accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.figure()\n",
    "\n",
    "plt.plot(epochs, loss, 'bo', label='Training loss')\n",
    "plt.plot(epochs, val_loss, 'b', label='Validation loss')\n",
    "plt.title('Training and validation loss')\n",
    "plt.legend()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "77f7809c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40b275f2",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "a93132bb",
   "metadata": {},
   "outputs": [],
   "source": [
    "#change working directory\n",
    "os.chdir('C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\FOUR_CARNIVORES\\\\models')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "1536eb31",
   "metadata": {},
   "outputs": [],
   "source": [
    "#ENSEMBLE LEARNING"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1a266eb4",
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras.preprocessing import image\n",
    "import keras.backend as K\n",
    "import numpy as np\n",
    "import cv2\n",
    "import sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "b399def3",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar modelo:\n",
    "from keras.models import model_from_json\n",
    "# cargar json y crear el modelo\n",
    "json_file = open('Resnet50-swish-Adagrad.json', 'r')\n",
    "loaded_model_json = json_file.read()\n",
    "json_file.close()\n",
    "model1 = model_from_json(loaded_model_json)#change sequentially\n",
    "# cargar pesos al nuevo modelo\n",
    "model1.load_weights(\"Resnet50-swish-Adagrad.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "f336fd20",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar modelo:\n",
    "from keras.models import model_from_json\n",
    "# cargar json y crear el modelo\n",
    "json_file = open('densenet-relu-Adagrad.json', 'r')\n",
    "loaded_model_json = json_file.read()\n",
    "json_file.close()\n",
    "model2 = model_from_json(loaded_model_json)#change sequentially\n",
    "# cargar pesos al nuevo modelo\n",
    "model2.load_weights(\"densenet-relu-Adagrad.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "b10d0f88",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar modelo:\n",
    "from keras.models import model_from_json\n",
    "# cargar json y crear el modelo\n",
    "json_file = open('vgg19-swish-Adagrad.json', 'r')\n",
    "loaded_model_json = json_file.read()\n",
    "json_file.close()\n",
    "model3 = model_from_json(loaded_model_json)#change sequentially\n",
    "# cargar pesos al nuevo modelo\n",
    "model3.load_weights(\"vgg19-swish-Adagrad.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "86b12a64",
   "metadata": {},
   "outputs": [],
   "source": [
    "members=[model1,model2,model3]#actualizar!!!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "id": "46a17b78",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Stacked Test Accuracy: 0.804\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import cross_val_score\n",
    "from sklearn.metrics import accuracy_score\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.ensemble import ExtraTreesClassifier\n",
    "from sklearn.ensemble import GradientBoostingClassifier\n",
    "from sklearn.ensemble import AdaBoostClassifier\n",
    "from sklearn.ensemble import BaggingClassifier\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from keras.models import load_model\n",
    "from keras.utils import to_categorical\n",
    "from numpy import dstack\n",
    "\n",
    " \n",
    "# create stacked model input dataset as outputs from the ensemble\n",
    "def stacked_dataset(members, inputX):\n",
    "\tstackX = None\n",
    "\tfor model in members:\n",
    "\t\t# make prediction\n",
    "\t\tyhat = model.predict(inputX, verbose=0)\n",
    "\t\t# stack predictions into [rows, members, probabilities]\n",
    "\t\tif stackX is None:\n",
    "\t\t\tstackX = yhat\n",
    "\t\telse:\n",
    "\t\t\tstackX = dstack((stackX, yhat))\n",
    "\t# flatten predictions to [rows, members x probabilities]\n",
    "\tstackX = stackX.reshape((stackX.shape[0], stackX.shape[1]*stackX.shape[2]))\n",
    "\treturn stackX\n",
    " \n",
    "# fit a model based on the outputs from the ensemble members\n",
    "def fit_stacked_model(members, inputX, inputy):\n",
    "\t# create dataset using ensemble\n",
    "\tstackedX = stacked_dataset(members, inputX)\n",
    "\t# fit standalone model\n",
    "\t#model = LogisticRegression()#\n",
    "\t#model = RandomForestClassifier(n_estimators=100, max_depth=None,max_features=20,min_samples_split=2, random_state=0)# n_estimators=n of trees\n",
    "\tmodel = ExtraTreesClassifier()\n",
    "\t#model = GradientBoostingClassifier()\n",
    "\t#model = AdaBoostClassifier(n_estimators=100)\n",
    "\t#model = BaggingClassifier(KNeighborsClassifier(),max_samples=0.5, max_features=0.5)\n",
    "\tmodel.fit(stackedX, inputy)\n",
    "\treturn model\n",
    " \n",
    "# make a prediction with the stacked model\n",
    "def stacked_prediction(members, model, inputX):\n",
    "\t# create dataset using ensemble\n",
    "\tstackedX = stacked_dataset(members, inputX)\n",
    "\t# make a prediction\n",
    "\tyhat = model.predict(stackedX)\n",
    "\treturn yhat\n",
    " \n",
    "\n",
    "# fit stacked model using the ensemble\n",
    "model = fit_stacked_model(members, x_train, y_train)\n",
    "# evaluate model on test set\n",
    "yhat = stacked_prediction(members, model, x_test)\n",
    "acc = accuracy_score(y_test, yhat)\n",
    "print('Stacked Test Accuracy: %.3f' % acc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "id": "historical-forth",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "\n",
    "filename = \"stacked_model.pickle\"\n",
    "\n",
    "# save model\n",
    "pickle.dump(model, open(filename, \"wb\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "id": "soviet-breed",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "        croc       1.00      0.65      0.79        26\n",
      "       hyena       0.89      0.82      0.86        62\n",
      "     leopard       0.67      0.94      0.78        36\n",
      "        lion       0.94      0.74      0.83        39\n",
      "\n",
      "   micro avg       0.84      0.80      0.82       163\n",
      "   macro avg       0.87      0.79      0.81       163\n",
      "weighted avg       0.87      0.80      0.82       163\n",
      " samples avg       0.80      0.80      0.80       163\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\oscar\\anaconda3\\Lib\\site-packages\\sklearn\\metrics\\_classification.py:1469: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in samples with no predicted labels. Use `zero_division` parameter to control this behavior.\n",
      "  _warn_prf(average, modifier, msg_start, len(result))\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import classification_report\n",
    "vp=np.round(yhat)\n",
    "vt=y_test\n",
    "target_names = [ \"croc\",'hyena','leopard', 'lion']\n",
    "print(classification_report(vt,vp,target_names=target_names))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "orange-surgery",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 153,
   "id": "9025e99b",
   "metadata": {},
   "outputs": [],
   "source": [
    "#loads image to be classified. Activate libraries\n",
    "\n",
    "from tensorflow.keras.preprocessing import image\n",
    "import keras.backend as K\n",
    "import numpy as np\n",
    "import cv2\n",
    "import sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "70341e5d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "abbcc878",
   "metadata": {},
   "outputs": [],
   "source": [
    "#make independent model predictions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5ddbc2a7",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from keras.applications.resnet50 import preprocess_input as preprocess_resnet50\n",
    "\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for ResNet50\n",
    "    img_resnet50 = image.img_to_array(img)\n",
    "    img_resnet50 = np.expand_dims(img_resnet50, axis=0)\n",
    "    img_resnet50 = preprocess_resnet50(img_resnet50)\n",
    "\n",
    "    # Make predictions with each model\n",
    "    prediction_resnet50 = members[0].predict(img_resnet50)\n",
    "    \n",
    "    # Extract label from the image file name\n",
    "    label = file_name.split('.')[0]  # Assuming the label is the part of the file name before the first period\n",
    "    \n",
    "    # Print the final prediction and the corresponding label\n",
    "    print('Prediction:', prediction_resnet50, 'Label:', label)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "1dbf5c7b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 85ms/step\n",
      "1/1 [==============================] - 0s 65ms/step\n",
      "1/1 [==============================] - 0s 63ms/step\n",
      "1/1 [==============================] - 0s 62ms/step\n",
      "          Label                                         Prediction\n",
      "0   FKLKN+45+1+  [[0.0011018771, 0.97842133, 0.0044411197, 0.01...\n",
      "1   FLKN+410+3+  [[0.00070779334, 0.99411833, 0.0048674904, 0.0...\n",
      "2   FLKN+49d+3+  [[0.20154403, 0.49592334, 0.067333855, 0.23519...\n",
      "3  FLKN+811+13+  [[0.086325526, 0.89340276, 0.008510469, 0.0117...\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import pandas as pd\n",
    "from keras.applications.resnet50 import preprocess_input as preprocess_resnet50\n",
    "\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select2'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Create lists to store results\n",
    "labels = []\n",
    "predictions = []\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for ResNet50\n",
    "    img_resnet50 = image.img_to_array(img)\n",
    "    img_resnet50 = np.expand_dims(img_resnet50, axis=0)\n",
    "    img_resnet50 = preprocess_resnet50(img_resnet50)\n",
    "\n",
    "    # Make predictions with each model\n",
    "    prediction_resnet50 = members[0].predict(img_resnet50)\n",
    "    \n",
    "    # Extract label from the image file name\n",
    "    label = file_name.split('.')[0]  # Assuming the label is the part of the file name before the first period\n",
    "    \n",
    "    # Append results to lists\n",
    "    labels.append(label)\n",
    "    predictions.append(prediction_resnet50)\n",
    "\n",
    "# Create a DataFrame\n",
    "results_df = pd.DataFrame({\n",
    "    'Label': labels,\n",
    "    'Prediction': predictions\n",
    "})\n",
    "\n",
    "# Print the DataFrame\n",
    "print(results_df)\n",
    "\n",
    "\n",
    "\n",
    "# Export the DataFrame to a CSV file in the folder_path\n",
    "#results_df.to_csv(os.path.join(folder_path, 'predictionsResnet.csv'), index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "b77f5ebd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 121ms/step\n",
      "1/1 [==============================] - 0s 168ms/step\n",
      "1/1 [==============================] - 0s 139ms/step\n",
      "1/1 [==============================] - 0s 118ms/step\n",
      "          Label                                         Prediction\n",
      "0   FKLKN+45+1+  [[0.016972942, 0.960585, 0.004298272, 0.018143...\n",
      "1   FLKN+410+3+  [[0.08442394, 0.8966148, 0.003621311, 0.0153399]]\n",
      "2   FLKN+49d+3+  [[0.901319, 0.03879589, 0.021901509, 0.03798359]]\n",
      "3  FLKN+811+13+  [[0.12944134, 0.8490778, 0.015581769, 0.005899...\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import pandas as pd\n",
    "from keras.applications.densenet import preprocess_input as preprocess_densenet\n",
    "\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select2'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Create lists to store results\n",
    "labels = []\n",
    "predictions = []\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for ResNet50\n",
    "    img_dense = image.img_to_array(img)\n",
    "    img_dense = np.expand_dims(img_dense, axis=0)\n",
    "    img_dense = preprocess_densenet(img_dense)\n",
    "\n",
    "    # Make predictions with each model\n",
    "    prediction_dense = members[1].predict(img_dense)\n",
    "    \n",
    "    # Extract label from the image file name\n",
    "    label = file_name.split('.')[0]  # Assuming the label is the part of the file name before the first period\n",
    "    \n",
    "    # Append results to lists\n",
    "    labels.append(label)\n",
    "    predictions.append(prediction_dense)\n",
    "\n",
    "# Create a DataFrame\n",
    "results_df = pd.DataFrame({\n",
    "    'Label': labels,\n",
    "    'Prediction': predictions\n",
    "})\n",
    "\n",
    "# Print the DataFrame\n",
    "print(results_df)\n",
    "\n",
    "\n",
    "\n",
    "# Export the DataFrame to a CSV file in the folder_path\n",
    "#results_df.to_csv(os.path.join(folder_path, 'predictionsResnet.csv'), index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "0fb3c279",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 83ms/step\n",
      "1/1 [==============================] - 0s 81ms/step\n",
      "1/1 [==============================] - 0s 78ms/step\n",
      "1/1 [==============================] - 0s 80ms/step\n",
      "          Label                                         Prediction\n",
      "0   FKLKN+45+1+  [[4.8993643e-05, 0.97984535, 0.014743663, 0.00...\n",
      "1   FLKN+410+3+  [[0.23927452, 0.75965506, 0.0008251995, 0.0002...\n",
      "2   FLKN+49d+3+  [[0.026008101, 0.3158335, 0.060618635, 0.59753...\n",
      "3  FLKN+811+13+  [[0.023932086, 0.96286744, 0.0007293139, 0.012...\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "from keras.applications.vgg19 import preprocess_input as preprocess_vgg19\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select2'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Create lists to store results\n",
    "labels = []\n",
    "predictions = []\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for Densenet\n",
    "    img_vgg = image.img_to_array(img)\n",
    "    img_vgg = np.expand_dims(img_vgg, axis=0)\n",
    "    img_vgg = preprocess_vgg19(img_vgg)\n",
    "\n",
    "    # Make predictions with each model\n",
    "    prediction_vgg = members[2].predict(img_vgg)\n",
    "    \n",
    "    # Extract label from the image file name\n",
    "    label = file_name.split('.')[0]  # Assuming the label is the part of the file name before the first period\n",
    "    \n",
    "        # Append results to lists\n",
    "    labels.append(label)\n",
    "    predictions.append(prediction_vgg)\n",
    "\n",
    "# Create a DataFrame\n",
    "results_df = pd.DataFrame({\n",
    "    'Label': labels,\n",
    "    'Prediction': predictions\n",
    "})\n",
    "\n",
    "# Print the DataFrame\n",
    "print(results_df)\n",
    "\n",
    "\n",
    "\n",
    "# Export the DataFrame to a CSV file in the folder_path\n",
    "#results_df.to_csv(os.path.join(folder_path, 'predictionsResnet.csv'), index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "42e0cc81",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cathedral-maker",
   "metadata": {},
   "outputs": [],
   "source": [
    "#now ensemble the three models:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "8cf231ed",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 61ms/step\n",
      "1/1 [==============================] - 0s 112ms/step\n",
      "1/1 [==============================] - 0s 69ms/step\n",
      "[[0.01997947 0.683821   0.26666063 0.02953891]]\n"
     ]
    }
   ],
   "source": [
    "from keras.preprocessing import image\n",
    "from keras.applications.resnet50 import preprocess_input as preprocess_resnet50\n",
    "from keras.applications.vgg19 import preprocess_input as preprocess_vgg19\n",
    "from keras.applications.densenet import preprocess_input as preprocess_densenet\n",
    "import numpy as np\n",
    "\n",
    "# Load the image\n",
    "img = image.load_img('C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select\\\\FKLKN+45+1+.bmp', target_size=(250, 200))\n",
    "\n",
    "# Preprocess the image for ResNet50\n",
    "img_resnet50 = image.img_to_array(img)\n",
    "img_resnet50 = np.expand_dims(img_resnet50, axis=0)\n",
    "img_resnet50 = preprocess_resnet50(img_resnet50)\n",
    "\n",
    "# Preprocess the image for VGG19\n",
    "img_vgg19 = image.img_to_array(img)\n",
    "img_vgg19 = np.expand_dims(img_vgg19, axis=0)\n",
    "img_vgg19 = preprocess_vgg19(img_vgg19)\n",
    "\n",
    "# Preprocess the image for DenseNet\n",
    "img_densenet = image.img_to_array(img)\n",
    "img_densenet = np.expand_dims(img_densenet, axis=0)\n",
    "img_densenet = preprocess_densenet(img_densenet)\n",
    "\n",
    "# Now, you can make predictions with each model in your ensemble\n",
    "# For example, if `members` is a list containing your three models\n",
    "prediction_resnet50 = members[0].predict(img_resnet50)\n",
    "prediction_densenet = members[1].predict(img_densenet)\n",
    "prediction_vgg19 = members[2].predict(img_vgg19)\n",
    "\n",
    "# Combine predictions according to your ensemble strategy\n",
    "# For example, you might average probabilities\n",
    "final_prediction = (prediction_resnet50 + prediction_vgg19 + prediction_densenet) / 3\n",
    "print(final_prediction)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "f0c08bfa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.05771337 1.9989927  0.73263305 0.08566102]]\n"
     ]
    }
   ],
   "source": [
    "# Define the accuracies of the models\n",
    "accuracies = [80, 77, 73]\n",
    "\n",
    "# Find the maximum accuracy\n",
    "max_accuracy = max(accuracies)\n",
    "\n",
    "# Calculate the weights\n",
    "weights = [(accuracy / max_accuracy) for accuracy in accuracies]\n",
    "\n",
    "# Now you have the weights for each model\n",
    "# You can use these weights to combine the predictions\n",
    "weighted_prediction = (prediction_resnet50 * weights[0] +\n",
    "                       prediction_densenet * weights[1] +\n",
    "                       prediction_vgg19 * weights[2])\n",
    "\n",
    "print(weighted_prediction)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "beaf178f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.02007421 0.69530183 0.2548289  0.02979514]]\n"
     ]
    }
   ],
   "source": [
    "# Define the accuracies of the models\n",
    "accuracies = [80, 77, 73]\n",
    "\n",
    "# Find the maximum accuracy\n",
    "max_accuracy = max(accuracies)\n",
    "\n",
    "# Calculate the weights\n",
    "weights = [(accuracy / max_accuracy) for accuracy in accuracies]\n",
    "\n",
    "# Now you have the weights for each model\n",
    "# You can use these weights to combine the predictions\n",
    "weighted_prediction = (prediction_resnet50 * weights[0] +\n",
    "                       prediction_densenet * weights[1] +\n",
    "                       prediction_vgg19 * weights[2])\n",
    "\n",
    "# Normalize the weighted prediction\n",
    "total_sum = weighted_prediction.sum()\n",
    "normalized_prediction = weighted_prediction / total_sum\n",
    "\n",
    "print(normalized_prediction)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "id": "3f71c0f7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 81ms/step\n",
      "1/1 [==============================] - 0s 123ms/step\n",
      "1/1 [==============================] - 0s 84ms/step\n",
      "[[0.01997947 0.683821   0.26666063 0.02953891]]\n",
      "1/1 [==============================] - 0s 72ms/step\n",
      "1/1 [==============================] - 0s 109ms/step\n",
      "1/1 [==============================] - 0s 88ms/step\n",
      "[[0.0168046  0.93213445 0.02103366 0.0300272 ]]\n",
      "1/1 [==============================] - 0s 74ms/step\n",
      "1/1 [==============================] - 0s 126ms/step\n",
      "1/1 [==============================] - 0s 83ms/step\n",
      "[[0.17767024 0.5407266  0.03123184 0.25037137]]\n",
      "1/1 [==============================] - 0s 58ms/step\n",
      "1/1 [==============================] - 0s 110ms/step\n",
      "1/1 [==============================] - 0s 68ms/step\n",
      "[[0.00944577 0.9015882  0.04601304 0.04295301]]\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for ResNet50\n",
    "    img_resnet50 = image.img_to_array(img)\n",
    "    img_resnet50 = np.expand_dims(img_resnet50, axis=0)\n",
    "    img_resnet50 = preprocess_resnet50(img_resnet50)\n",
    "\n",
    "# Preprocess the image for VGG19\n",
    "    img_vgg19 = image.img_to_array(img)\n",
    "    img_vgg19 = np.expand_dims(img_vgg19, axis=0)\n",
    "    img_vgg19 = preprocess_vgg19(img_vgg19)\n",
    "\n",
    "# Preprocess the image for DenseNet\n",
    "    img_densenet = image.img_to_array(img)\n",
    "    img_densenet = np.expand_dims(img_densenet, axis=0)\n",
    "    img_densenet = preprocess_densenet(img_densenet)\n",
    "\n",
    "# Now, you can make predictions with each model in your ensemble\n",
    "# For example, if `members` is a list containing your three models\n",
    "    prediction_resnet50 = members[0].predict(img_resnet50)\n",
    "    prediction_densenet = members[1].predict(img_densenet)\n",
    "    prediction_vgg19 = members[2].predict(img_vgg19)\n",
    "\n",
    "    # Combine predictions according to the ensemble strategy\n",
    "    final_prediction = (prediction_resnet50 + prediction_vgg19 + prediction_densenet) / 3\n",
    "    print(final_prediction)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "387b4595",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1/1 [==============================] - 0s 67ms/step\n",
      "1/1 [==============================] - 0s 113ms/step\n",
      "1/1 [==============================] - 0s 86ms/step\n",
      "Prediction: [[0.00604127 0.97295064 0.00782769 0.01318045]] Label: FKLKN+45+1+\n",
      "Weighted Prediction: [[0.00607366 0.97290987 0.00764494 0.01337147]] Label: FKLKN+45+1+\n",
      "1/1 [==============================] - 0s 62ms/step\n",
      "1/1 [==============================] - 0s 121ms/step\n",
      "1/1 [==============================] - 0s 87ms/step\n",
      "Prediction: [[0.10813541 0.8834627  0.00310467 0.00529719]] Label: FLKN+410+3+\n",
      "Weighted Prediction: [[0.10397901 0.88753456 0.00317524 0.00531127]] Label: FLKN+410+3+\n",
      "1/1 [==============================] - 0s 70ms/step\n",
      "1/1 [==============================] - 0s 128ms/step\n",
      "1/1 [==============================] - 0s 88ms/step\n",
      "Prediction: [[0.3762904  0.28351757 0.04995133 0.2902407 ]] Label: FLKN+49d+3+\n",
      "Weighted Prediction: [[0.380007   0.28631458 0.05003108 0.28364733]] Label: FLKN+49d+3+\n",
      "1/1 [==============================] - 0s 63ms/step\n",
      "1/1 [==============================] - 0s 148ms/step\n",
      "1/1 [==============================] - 0s 84ms/step\n",
      "Prediction: [[0.07989965 0.9017827  0.00827385 0.01004381]] Label: FLKN+811+13+\n",
      "Weighted Prediction: [[0.0810429  0.90051305 0.00841789 0.01002616]] Label: FLKN+811+13+\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "\n",
    "# Define the accuracies of the models\n",
    "accuracies = [81, 77.3, 73]\n",
    "\n",
    "# Find the maximum accuracy\n",
    "max_accuracy = max(accuracies)\n",
    "\n",
    "# Calculate the weights\n",
    "weights = [(accuracy / max_accuracy) for accuracy in accuracies]\n",
    "\n",
    "\n",
    "\n",
    "# Path to the folder containing images\n",
    "folder_path = 'C:\\\\Users\\\\oscar\\\\Documents\\\\MOMOCS\\\\select2'\n",
    "\n",
    "# List all files in the folder\n",
    "image_files = os.listdir(folder_path)\n",
    "\n",
    "# Iterate over each image file\n",
    "for file_name in image_files:\n",
    "    # Load the image\n",
    "    img_path = os.path.join(folder_path, file_name)\n",
    "    img = image.load_img(img_path, target_size=(250, 200))\n",
    "\n",
    "    # Preprocess the image for ResNet50\n",
    "    img_resnet50 = image.img_to_array(img)\n",
    "    img_resnet50 = np.expand_dims(img_resnet50, axis=0)\n",
    "    img_resnet50 = preprocess_resnet50(img_resnet50)\n",
    "\n",
    "# Preprocess the image for VGG19\n",
    "    img_vgg19 = image.img_to_array(img)\n",
    "    img_vgg19 = np.expand_dims(img_vgg19, axis=0)\n",
    "    img_vgg19 = preprocess_vgg19(img_vgg19)\n",
    "\n",
    "# Preprocess the image for DenseNet\n",
    "    img_densenet = image.img_to_array(img)\n",
    "    img_densenet = np.expand_dims(img_densenet, axis=0)\n",
    "    img_densenet = preprocess_densenet(img_densenet)\n",
    "\n",
    "# Now, you can make predictions with each model in your ensemble\n",
    "# For example, if `members` is a list containing your three models\n",
    "    prediction_resnet50 = members[0].predict(img_resnet50)\n",
    "    prediction_densenet = members[1].predict(img_densenet)\n",
    "    prediction_vgg19 = members[2].predict(img_vgg19)\n",
    "\n",
    "    # Combine predictions according to the ensemble strategy\n",
    "    final_prediction = (prediction_resnet50 + prediction_vgg19 + prediction_densenet) / 3\n",
    "    \n",
    "    #weighted prediction\n",
    "    # Now you have the weights for each model\n",
    "    # You can use these weights to combine the predictions\n",
    "    weighted_prediction = (prediction_resnet50 * weights[0] +prediction_densenet * weights[1] +\n",
    "                       prediction_vgg19 * weights[2])\n",
    "    # Normalize the weighted prediction\n",
    "    total_sum = weighted_prediction.sum()\n",
    "    normalized_prediction = weighted_prediction / total_sum\n",
    "    \n",
    "    # Extract label from the image file name\n",
    "    label = file_name.split('.')[0]  # Assuming the label is the part of the file name before the first period\n",
    "    \n",
    "    # Print the final prediction and the corresponding label\n",
    "    print('Prediction:', final_prediction, 'Label:', label)\n",
    "    \n",
    "        # Print the final prediction and the corresponding label\n",
    "    print('Weighted Prediction:', normalized_prediction, 'Label:', label)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "78babc8d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e43bd6b2",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "906acc1c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0547d4e4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f278df62",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75fdb63b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
